﻿using Douglas.Tool.Configure;
using Douglas.Tool.Entity;
using Douglas.Tool.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Text;

namespace Douglas.Tool.Filters
{
    public class ApiAuthorizeFilter : IAuthorizationFilter
    {
        public ApiAuthorizeFilter()
        {

        }
        /// <summary>
        /// 只判断token是否正确，不判断权限
        /// 如果需要判断权限的在Action上加上ApiActionPermission属性标识权限类别，ActionPermissionFilter作权限处理
        ///(string,string,string)1、请求参数,2、返回消息，3,异常消息,4状态
        /// </summary>
        /// <param name="context"></param>
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            if (context.ActionDescriptor.EndpointMetadata.Any(item => item is AllowAnonymousAttribute))
            {
                return;
            }
            // &&UserContext.Current.UserName!="admin666"为演示环境，实际使用时去掉此条件
            if (!context.HttpContext.User.Identity.IsAuthenticated ||
                (UserContext.Current.Token != ((ClaimsIdentity)context.HttpContext.User.Identity)?.BootstrapContext?.ToString()))
            {
                Console.Write($"IsAuthenticated:{context.HttpContext.User.Identity.IsAuthenticated}," +
                    $"userToken{UserContext.Current.Token}" +
                    $"BootstrapContext:{((ClaimsIdentity)context.HttpContext.User.Identity)?.BootstrapContext?.ToString()}");
                context.Result = new ContentResult()
                {
                    Content = new { message= "登陆已过期", status = false, code = (int)HttpStatusCode.Unauthorized }.Serialize(),
                    ContentType = "application/json",
                    StatusCode = (int)HttpStatusCode.Unauthorized
                };
                return;
            }

            DateTime expDate = context.HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp)
                .Select(x => x.Value).FirstOrDefault().GetTimeSpmpToDate();
            //如果过期时间小于设置定分钟数的1/3时，返回状态需要刷新token
            if (expDate < DateTime.Now || (expDate - DateTime.Now).TotalMinutes < AppSetting.ExpMinutes / 3)
            {
                context.Result = new ContentResult()
                {
                    Content = new { message = "Token即将过期,请更换token", status = false, code = (int)HttpStatusCode.Accepted }.Serialize(),
                    ContentType = "application/json",
                    StatusCode = (int)HttpStatusCode.Accepted
                };//202
                return;
            }
        }
    }
}
